package com.lezai.zookeeper.lock;

import org.I0Itec.zkclient.IZkDataListener;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ZkWriteLock extends ZkAbstractLock {
    private String lockPath;
    private String currentPath;
    private String beforePath;

    public ZkWriteLock(String lockPath) {
        if (!zkClient.exists(PATH)) {
            zkClient.createPersistent(PATH);
        }
        this.lockPath = PATH + "/" + lockPath;
        if (!zkClient.exists(this.lockPath)) {
            System.out.println("-----------");
            zkClient.createPersistent(this.lockPath);
        }
    }

    public boolean tryLock() {
        if (null == currentPath || currentPath.length() <= 0) {
            currentPath = zkClient.createEphemeralSequential(lockPath + "/write", "lock");
        }
        List<String> children = zkClient.getChildren(lockPath);

        Collections.sort(children, Comparator.comparingInt(o -> Integer.parseInt(o.replaceAll("[^0-9]*", ""))));
//        System.out.println("当前孩子:"+children.toString());
        if (currentPath.equals(lockPath + "/" + children.get(0))) {
            System.out.println("成功获取锁：" + currentPath);
            return true;
        }
        String key = currentPath.substring(lockPath.length() + 1);
        int location = children.indexOf(key);
        this.beforePath = lockPath + "/" + children.get(location - 1);
        System.out.println("获取写锁失败"+key);
        System.out.println("当前孩子:"+children.toString());
        return false;
    }

    public void waitLock() {
        CountDownLatch LATCH = new CountDownLatch(1);
        IZkDataListener listener = new IZkDataListener() {
            public void handleDataChange(String s, Object o) {
            }

            public void handleDataDeleted(String s) {
                System.out.println(s+"handleDataDeleted");
                LATCH.countDown();
            }
        };
        System.out.println("监听节点:"+this.beforePath);
        zkClient.subscribeDataChanges(this.beforePath, listener);
        if (!zkClient.exists(this.beforePath)) {
            return;
        }
        try {
            System.out.println("节点结束等待:"+currentPath);
            LATCH.await();
            System.out.println("节点结束等待:"+currentPath);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        zkClient.unsubscribeDataChanges(this.beforePath, listener);
    }

    @Override
    public void unLock() {
//        System.out.println("成功释放锁"+currentPath);
        zkClient.delete(currentPath);
        super.unLock();
    }
}